Port experimentation service and reporting to extension#3675
Port experimentation service and reporting to extension#3675DanielRosenwasser merged 12 commits intomainfrom
Conversation
| "@vscode/extension-telemetry": "^1.5.1", | ||
| "vscode-languageclient": "^10.0.0-next.21" | ||
| "vscode-languageclient": "^10.0.0-next.21", | ||
| "vscode-tas-client": "0.1.84" |
There was a problem hiding this comment.
Locked on 0.1.84 because of microsoft/tas-client#95
There was a problem hiding this comment.
Pull request overview
Ports VS Code TAS (experimentation) plumbing into the native-preview VS Code extension so telemetry can include shared experimentation context (flights/treatments) and the extension can query treatment variables.
Changes:
- Add
vscode-tas-clientdependency and wire experimentation telemetry into the existing telemetry reporter. - Introduce an
ExperimentationServicewrapper plus a helper to read extension package name/version for TAS initialization. - Update extension activation to construct the experimentation service during startup; add a new
_extension/pnpm-lock.yaml.
Show a summary per file
| File | Description |
|---|---|
| package-lock.json | Adds vscode-tas-client (and transitive tas-client) to the workspace lockfile. |
| _extension/package.json | Declares vscode-tas-client dependency for the extension workspace. |
| _extension/pnpm-lock.yaml | Adds a pnpm lockfile for the extension workspace. |
| _extension/tsconfig.json | Changes TS module setting to preserve for the extension project. |
| _extension/src/util.ts | Adds getPackageInfo helper for extension id/version discovery. |
| _extension/src/telemetryReporting.ts | Extends the telemetry reporter to implement IExperimentationTelemetry and inject shared properties. |
| _extension/src/extension.ts | Instantiates ExperimentationService during activation. |
| _extension/src/experimentationService.ts | New TAS experimentation service wrapper and initialization logic. |
| _extension/src/commands.ts | Removes an unused import. |
Copilot's findings
Files not reviewed (1)
- _extension/pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
_extension/src/experimentationService.ts:62
createTasExperimentationServiceawaitsexperimentationService.initialFetchand will reject if the fetch fails. SinceExperimentationServiceconstructs this promise without attaching a rejection handler (andactivatedoesn't await it), this can trigger an unhandled promise rejection during activation. Consider catching/logging fetch errors insidecreateTasExperimentationService(or in the constructor) and returning a usable service that falls back gracefully.
const experimentationService = tas.getExperimentationService(id, version, targetPopulation, reporter, globalState);
await experimentationService.initialFetch;
return experimentationService;
- Files reviewed: 7/9 changed files
- Comments generated: 4
| public async getTreatmentVariable<K extends keyof ExperimentTypes>(name: K, defaultValue: ExperimentTypes[K]): Promise<ExperimentTypes[K]> { | ||
| const experimentationService = await this._experimentationServicePromise; | ||
| try { | ||
| const treatmentVariable = await experimentationService.getTreatmentVariableAsync("vscode", name, /*checkCache*/ true) as ExperimentTypes[K]; | ||
| return treatmentVariable ?? defaultValue; | ||
| } | ||
| catch { | ||
| return defaultValue; | ||
| } |
| const packageInfo = getPackageInfo(context); | ||
| if (packageInfo) { | ||
| const { name: id, version } = packageInfo; | ||
| // Constructing the experimentation service actually sets shared properties | ||
| // so that events include context on treatments/flights. | ||
| const _expService = new ExperimentationService(telemetryReporter, id, version, context.globalState); | ||
| } |
There was a problem hiding this comment.
For now this is fine, we are just using this to stamp common properties like the assignment context. I could just void it.
This blocks actually constructing the service which basically delays extension loads. Our `getTreatmentVariable` calls `getTreatmentVariableAsync`, which calls their `getFeaturesAsync` and actually resolves the initial fetch.
| "compilerOptions": { | ||
| "target": "es2023", | ||
| "module": "NodeNext", | ||
| "module": "preserve", |
There was a problem hiding this comment.
we bundle, so maybe this should be bundler mode?
There was a problem hiding this comment.
I actually don't think I needed to make this change. I might undo it.
Though I think that preserve implies bundler, right?
|
|
||
| const packageInfo = getPackageInfo(context); | ||
| if (packageInfo) { | ||
| const { name: id, version } = packageInfo; |
There was a problem hiding this comment.
Not just context.extension.id?
There was a problem hiding this comment.
No, name is native-preview, context.extension.id would be TypeScriptTeam.native-preview
There was a problem hiding this comment.
well right, but surely the exp platform wants more of a name than native-preview?
There was a problem hiding this comment.
You are right and I think that the built-in extension was doing this wrong.
There was a problem hiding this comment.
Oh, yeah, because builtin extensions don't have a publisher name and that's how they are determined to be builtins
No description provided.